Home:ALL Converter>Oracle avg in group by not sorting properly

Oracle avg in group by not sorting properly

Ask Time:2019-01-05T03:52:56         Author:MarkRx

Json Formatter

We are receiving incorrect result ordering when using an order by on an aggregate function in a group by clause on Oracle 12.2. After playing around with it we have found that the query only works when it is phrased in certain ways (see below).

So here are our questions:

1) Why is ordering by avg acting finicky? Are the queries acting as expected based on some documented logic / limitation? Does it have something to do with the underlying data type being number(16) without decimal places?

2) Why does using an alias in query 4 make it work while query 3 does not work?

3) Why do the queries work better when ordering by ascending duration? It's not shown below but query 2 works when asc even though it does not work desc. Query 1 does not work with asc.

In the below examples note that duration is a number(16).

Query 1: Avg function order by function

select
    name,
    avg(duration)
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg(duration) desc

-- Query 1 result (wrong)
(some name) 1224417.83471074
(some name) 33568438.1548673
(some name) 3928150.12809406
(some name) 1434939.13464658
(some name) 269338.574638521

Query 2: Avg function order by alias

-- Query 2: order by avg alias
select
    name,
    avg(duration) avg
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg desc

-- Query 2 result (wrong)
-- See query 1 result

-- Note: For some reason this query works correctly when ordered asc

Query 3: Avg function with cast order by function

select
    name,
    to_number(avg(duration))
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by to_number(avg(duration)) desc

-- Query 3 result (wrong)
-- See query 1 result

Query 4: Avg function with cast order by alias

select
    name,
    to_number(avg(duration)) avg
from table1
join table2 on table1.table2_id = table2.id
where duration is not null
group by name
order by avg desc

-- Query 4 results (correct)
(some name) 562654936
(some name) 498804314
(some name) 263681023
(some name) 245531731
(some name) 188103278
-- the values with decimals show up later in the right order

Query 5 & 6: Avg function with/without cast with ordering in an external query

select * from (
    select
        name,
        to_number(avg(duration)) avg -- works without to_number as well
    from table1
    join table2 on table1.table2_id = table2.id
    where duration is not null
    group by name
) order by avg desc

-- Query 5 & 6 results (correct)
-- See query 4 results

Author:MarkRx,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/54045193/oracle-avg-in-group-by-not-sorting-properly
Himanshu :

I guess for correct output results you need to have the aggregation done already but here what happens is the aggregation when done after grouping again in order by you are having aggregation so this again starts aggregation on top of the aggregation already done even though its a alias using an outer query is most efficient to first finalize the output after aggregation then have the order by in the outer query like select col1,col2 from (select col,agg(..) from table group by col) order by col2 this will limit to only ordering the received output not again aggregating and ordering.",
2019-01-04T20:03:32
yy